package com.chennan.redis.domain.service;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author chennan
 * @createTime 2021年07月23日 13:54:00
 */
@Service
public class RedisServiceComplete {

    @Autowired
    private RedisTemplate<String, ?> redisTemplate;

    public RedisServiceComplete() {
    }

    public boolean setEx(final String key, final String value, final Integer seconds) {
        Boolean execute = this.redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                Boolean result = connection.setEx(serializer.serialize(key), (long) seconds, serializer.serialize(value));
                return result == null ? false : result;
            }
        });
        return execute;
    }

    public boolean setNX(final String key, final String value, final Integer seconds) {
        return (Boolean)this.redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                Boolean result = connection.set(serializer.serialize(key), serializer.serialize(value), Expiration.seconds((long)seconds), RedisStringCommands.SetOption.SET_IF_ABSENT);
                return result == null ? false : result;
            }
        });
    }

    public String get(final String key) {
        return (String)this.redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                byte[] value = connection.get(serializer.serialize(key));
                return (String)serializer.deserialize(value);
            }
        });
    }

    public boolean expire(String key, long expire) {
        Boolean result = this.redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        return result == null ? false : result;
    }

    public <T> boolean setList(String key, List<T> list, Integer seconds) {
        String value = JSON.toJSONString(list);
        return this.setEx(key, value, seconds);
    }

    public <T> List<T> getList(String key, Class<T> clz) {
        String json = this.get(key);
        if (json != null) {
            List<T> list = JSON.parseArray(json, clz);
            return list;
        } else {
            return null;
        }
    }

    public long lpush(final String key, Object obj) {
        final String value = JSON.toJSONString(obj);
        final Long execute = this.redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                long count = connection.lPush(serializer.serialize(key), new byte[][]{serializer.serialize(value)});
                return count;
            }
        });
        return execute;
    }

    public long rpush(final String key, Object obj) {
        final String value = JSON.toJSONString(obj);
        Long execute = this.redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                long count = connection.rPush(serializer.serialize(key), new byte[][]{serializer.serialize(value)});
                return count;
            }
        });
        return execute;
    }

    public String lpop(final String key) {
        return (String)this.redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = RedisServiceComplete.this.redisTemplate.getStringSerializer();
                byte[] res = connection.lPop(serializer.serialize(key));
                return (String)serializer.deserialize(res);
            }
        });
    }

    public void del(String key) {
        this.redisTemplate.delete(key);
    }

    public Long getExpire(String key) {
        return this.redisTemplate.getExpire(key);
    }





    /**
     * 向set中添加元素
     * @return
     */
    public Long sAdd(){
//        redisTemplate.execute(new RedisCallback<String>(){
//
//            @Override
//            public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
//                redisConnection.si
//                return null;
//            }
//        });
        return 1L;
    }

}
